package org.dromara.workflow.service.impl

import cn.hutool.core.bean.BeanUtil
import cn.hutool.core.util.ObjectUtil
import org.dromara.common.core.domain.dto.CompleteTaskDTO
import org.dromara.common.core.domain.dto.StartProcessDTO
import org.dromara.common.core.domain.dto.StartProcessReturnDTO
import org.dromara.common.core.exception.ServiceException
import org.dromara.common.core.service.WorkflowService
import org.dromara.common.core.utils.StringUtils
import org.dromara.workflow.common.ConditionalOnEnable
import org.dromara.workflow.common.enums.MessageTypeEnum
import org.dromara.workflow.domain.bo.CompleteTaskBo
import org.dromara.workflow.domain.bo.StartProcessBo
import org.dromara.workflow.service.IFlwDefinitionService
import org.dromara.workflow.service.IFlwInstanceService
import org.dromara.workflow.service.IFlwTaskService
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

/**
 * 通用 工作流服务实现
 *
 * @author LikeYouDo
 */
@ConditionalOnEnable
@Service
class WorkflowServiceImpl(
    private val flwInstanceService: IFlwInstanceService,
    private val flwDefinitionService: IFlwDefinitionService,
    private val flwTaskService: IFlwTaskService
) : WorkflowService {
    /**
     * 删除流程实例
     *
     * @param businessIds 业务id
     * @return 结果
     */
    override fun deleteInstance(businessIds: List<Long>?): Boolean {
        return flwInstanceService.deleteByBusinessIds(businessIds)
    }

    /**
     * 获取当前流程状态
     *
     * @param taskId 任务id
     */
    override fun getBusinessStatusByTaskId(taskId: Long?): String? {
        val flowInstance = flwInstanceService.selectByTaskId(taskId)
        return if (flowInstance != null) flowInstance.flowStatus else StringUtils.EMPTY
    }

    /**
     * 获取当前流程状态
     *
     * @param businessId 业务id
     */
    override fun getBusinessStatus(businessId: String?): String? {
        val flowInstance = flwInstanceService.selectInstByBusinessId(businessId)
        return if (flowInstance != null) flowInstance.flowStatus else StringUtils.EMPTY
    }

    /**
     * 设置流程变量
     *
     * @param instanceId 流程实例id
     * @param variables  流程变量
     */
    public override fun setVariable(instanceId: Long?, variables: Map<String, Any?>?) {
        flwInstanceService.setVariable(instanceId, variables)
    }

    /**
     * 获取流程变量
     *
     * @param instanceId 流程实例id
     */
    override fun instanceVariable(instanceId: Long?): Map<String, Any?>? {
        return flwInstanceService.instanceVariable(instanceId)
    }

    /**
     * 按照业务id查询流程实例id
     *
     * @param businessId 业务id
     * @return 结果
     */
    override fun getInstanceIdByBusinessId(businessId: String?): Long? {
        val flowInstance = flwInstanceService.selectInstByBusinessId(businessId)
        return flowInstance?.id
    }

    /**
     * 新增租户流程定义
     *
     * @param tenantId 租户id
     */
    override fun syncDef(tenantId: String?) {
        flwDefinitionService.syncDef(tenantId)
    }

    /**
     * 启动流程
     *
     * @param startProcess 参数
     */
    override fun startWorkFlow(startProcess: StartProcessDTO?): StartProcessReturnDTO {
        return flwTaskService.startWorkFlow(BeanUtil.toBean(startProcess, StartProcessBo::class.java))
    }

    /**
     * 办理任务
     * 系统后台发起审批 无用户信息 需要忽略权限
     * completeTask.getVariables().put("ignore", true);
     *
     * @param completeTask 参数
     */
    override fun completeTask(completeTask: CompleteTaskDTO?): Boolean {
        return flwTaskService.completeTask(BeanUtil.toBean(completeTask, CompleteTaskBo::class.java))
    }

    /**
     * 办理任务
     *
     * @param taskId  任务ID
     * @param message 办理意见
     */
    override fun completeTask(taskId: Long?, message: String?): Boolean {
        val completeTask = CompleteTaskBo()
        completeTask.taskId = taskId
        completeTask.message = message
        // 忽略权限(系统后台发起审批 无用户信息 需要忽略权限)
        completeTask.getVariables()["ignore"] = true
        return flwTaskService.completeTask(completeTask)
    }

    /**
     * 启动流程并办理第一个任务
     *
     * @param startProcess 参数
     */
    @Transactional(rollbackFor = [Exception::class])
    override fun startCompleteTask(startProcess: StartProcessDTO): Boolean {
        try {
            val processBo = StartProcessBo()
            processBo.businessId = startProcess.businessId
            processBo.flowCode = startProcess.flowCode
            processBo.variables = startProcess.variables
            processBo.handler = startProcess.handler

            val result = flwTaskService.startWorkFlow(processBo)
            val taskBo = CompleteTaskBo()
            taskBo.taskId = result.taskId
            taskBo.messageType = mutableListOf<String?>(MessageTypeEnum.SYSTEM_MESSAGE.code)
            taskBo.variables = startProcess.variables
            taskBo.handler = startProcess.handler

            val flag = flwTaskService.completeTask(taskBo)
            if (!flag) {
                throw ServiceException("流程发起异常")
            }
            return true
        } catch (e: Exception) {
            throw ServiceException(e.message)
        }
    }
}
